import std.stdio;

import core.memory;
import std.traits;

struct AA
{
    int i = 10;
    ~this()
    {
        writeln("AA ~this");
    }
}

class A
{
    this()
    {
      //  a = new AA();
    }
    
    ~this()
    {
        
    }

    AA  a;
}

void main()
{
    A b = new A();
    gcFree(b);
    AA * a = new  AA();
    gcFree(a);
    a = null;
    writeln("hahah");
    
    ubyte[]  d = new ubyte[100];
    auto c = d[50..$];
    gcFree(c,true);
  
    d = new ubyte[30];
    gcFree(d.ptr);
    
    A[] aaa = new A[100];
    gcFree(aaa.ptr);
}

pragma(inline,true)
void gcFree(T)(T obj) if(is(T == class) || is(T == interface))  
{
    destroy(obj);
    GC.free(cast(void *) obj);
}

pragma(inline,true)
void gcFree(T)(T * obj)   
{
    static if(is(T == struct)) //NOTE: when it call in dstor, the struct's ~this will exec twice.
        destroy((*obj));
    GC.free(obj);
}

pragma(inline,true)
void gcFree(void[] obj,bool index = false)   
{
    void * t = obj.ptr;
    if(index) t = GC.addrOf(t);
    GC.free(t);
}
